package com.tiantian.subject.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.tiantian.api.RemoteUserService;
import com.tiantian.common.core.domain.LoginUser;
import com.tiantian.common.core.exception.BusinessException;
import com.tiantian.common.core.utils.ServletUtils;
import com.tiantian.common.satoken.utils.LoginHelper;
import com.tiantian.minio.utils.JxFileUtils;
import com.tiantian.subject.domain.dto.AddFolderDto;
import com.tiantian.subject.domain.entity.UserFiles;
import com.tiantian.subject.domain.vo.QuestionBankFileVo;
import com.tiantian.subject.mapper.UserFilesMapper;
import com.tiantian.subject.service.QuestionBankService;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author tiantian
 */
@Service
@RequiredArgsConstructor
public class QuestionBankServiceImpl implements QuestionBankService {

    private final JxFileUtils jxFileUtils;
    private final UserFilesMapper userFilesMapper;
    @DubboReference
    private final RemoteUserService remoteUserService;

    // 默认前缀(桶名称)
    @Value("${jx-minio.baseBucketName}")
    private String BASE_BUCKET_NAME;

    @Override
    public QuestionBankFileVo getFileList(String curPath) {
        List<Item> items = jxFileUtils.listObjects(BASE_BUCKET_NAME, curPath);
        QuestionBankFileVo questionBankFileVo = new QuestionBankFileVo();
        // 文件信息
        List<QuestionBankFileVo.FileInfo> fileInfoList = new ArrayList<>();
        // 前端文件面包屑导航
        List<String> breadcrumb = List.of("/");
        if (StrUtil.isNotEmpty(curPath)) {
            breadcrumb = Arrays.stream(curPath.split("/")).filter(StrUtil::isNotBlank).toList();
        }
        for (Item item : items) {
            QuestionBankFileVo.FileInfo fileInfo = new QuestionBankFileVo.FileInfo();
            String fileName = ServletUtils.urlDecode(item.objectName());
            boolean isDir = item.isDir();
            fileInfo.setFileName(fileName);
            fileInfo.setIsDir(isDir);
            fileInfo.setSize(item.size());
            // 根据文件MD5值查询作者
            if (StrUtil.isNotEmpty(item.etag())) {
                UserFiles userFiles = userFilesMapper.selectByMD5(item.etag().replaceAll("\"", ""));
                if (ObjUtil.isNotNull(userFiles)) {
                    LoginUser loginUser = LoginHelper.getLoginUser();
                    Long curUserId = loginUser.getUserId();
                    Long userId = userFiles.getUserId();
                    if (Objects.equals(curUserId, userId)) {
                        fileInfo.setAuthor(loginUser.getNickName());
                    } else {
                        fileInfo.setAuthor(remoteUserService.getUserNickNameById(userId));
                    }
                }
            }
            // 设置修改时间
            if (!isDir) {
                fileInfo.setUpdateTime(Date.from(item.lastModified().toInstant()));
            }
            // 设置文件后缀
            if (!isDir) {
                fileInfo.setExtension(FileUtil.extName(fileName));
            } else {
                fileInfo.setExtension("dir");
            }
            fileInfoList.add(fileInfo);
        }
        questionBankFileVo.setFileInfoList(fileInfoList);
        List<QuestionBankFileVo.BreadcrumbInfo> breadcrumbInfoList = new ArrayList<>();
        QuestionBankFileVo.BreadcrumbInfo.BreadcrumbInfoBuilder breadcrumbInfoBuilder = QuestionBankFileVo.BreadcrumbInfo.builder();
        int index = 0;
        for (String path : breadcrumb) {
            QuestionBankFileVo.BreadcrumbInfo breadcrumbInfo = breadcrumbInfoBuilder.index(index).path(path).build();
            breadcrumbInfoList.add(breadcrumbInfo);
            index++;
        }
        questionBankFileVo.setBreadcrumb(breadcrumbInfoList);
        return questionBankFileVo;
    }


    @Override
    public void AddFolder(AddFolderDto addFolderDto) {
        // 校验文件名称是否符合规范
        String dirName = addFolderDto.getDirName();
        if (validateDirName(dirName)) {
            throw new BusinessException(StrUtil.format("文件夹名 {} 不正确。文件名不能包含下列任意字符: \\ / : * ? \" < > |", dirName));
        }
        String curPath = addFolderDto.getCurPath();
        // 判断当前文件夹是否有同名文件夹
        List<Item> items = jxFileUtils.listObjects(BASE_BUCKET_NAME, curPath);
        for (Item item : items) {
            if (Objects.equals(getLastPartAfterLastSlash(item.objectName()), curPath)) {
                throw new BusinessException("文件夹名" + dirName + "已经存在");
            }
        }
        String md5 = jxFileUtils.mkdir(curPath + dirName, BASE_BUCKET_NAME);
        // 将文件与用户进行关联
        userFilesMapper.insert(IdUtil.getSnowflakeNextId(), md5, LoginHelper.getUserId());
    }

    @Override
    public boolean deleteDirOrFile(String[] fileOrDirName) {
        jxFileUtils.removeObjects(BASE_BUCKET_NAME, fileOrDirName);
        return true;
    }

    public static boolean validateDirName(String dirName) {
        // 定义包含特殊字符的集合
        String specialCharacters = " \\/:*?\"<>|";
        for (int i = 0; i < specialCharacters.length(); i++) {
            if (dirName.contains(String.valueOf(specialCharacters.charAt(i)))) {
                return true;
            }
        }
        return false;
    }

    public static String getLastPartAfterLastSlash(String str) {
        // 统计"/"数量
        int count = StrUtil.count(str, "/");
        if (count == 1) {
            return str.replaceAll("/", "");
        }
        StringBuilder sb = new StringBuilder();
        int lastIndex = str.length() - 2;
        for (int i = lastIndex; i >= 0; i--) {
            char c = str.charAt(i);
            if (c == '/') {
                break;
            }
            sb.append(c);
        }
        return sb.reverse().toString();
    }


}
